package services

import (
	"github.com/boticord/backend/notifications/app"
	"github.com/boticord/backend/notifications/types"
	"github.com/gorilla/websocket"
	"go.uber.org/fx"
	"sync"
	"time"
)

type GetTokenInfoDto struct {
	Token string `json:"token"`
	ID    string `json:"id"`
}

type TokenInfoResponse struct {
	types.TokenInfo
}

type AuthService struct {
	// conn *nats.Conn
	rpc      *app.RPC
	emitter  *app.Emitter
	authMux  sync.Mutex
	sessions map[string]*types.TokenInfo
	tokens   map[string]string
}

func (t *AuthService) GetToken(id string) string {
	t.authMux.Lock()
	defer t.authMux.Unlock()
	return t.tokens[id]
}

func (t *AuthService) SetSession(id, token string, data *types.TokenInfo) {
	t.authMux.Lock()
	defer t.authMux.Unlock()
	t.sessions[id] = data
	t.tokens[id] = token
}

func (t *AuthService) GetSessions() map[string]*types.TokenInfo {
	t.authMux.Lock()
	defer t.authMux.Unlock()
	return t.sessions
}

func (t *AuthService) GetSession(id string) *types.TokenInfo {
	t.authMux.Lock()
	defer t.authMux.Unlock()
	return t.sessions[id]
}

func (t *AuthService) RemoveSession(id string) error {
	return t.emitter.GetConnection(id).Close()
}

func (t *AuthService) disconnectHandler(conn *websocket.Conn, id string) {
	t.authMux.Lock()
	defer t.authMux.Unlock()
	delete(t.sessions, id)
}

func (t *AuthService) connectHandler(conn *websocket.Conn, id string) {
	time.AfterFunc(time.Second*120, func() {
		if t.GetSession(id) == nil {
			conn.Close()
		}
	})
}

func (t *AuthService) GetTokenInfo(token string) (*types.TokenInfo, error) {
	return app.RpcCall[types.TokenInfo, GetTokenInfoDto](t.rpc, "users", "POST", "tokenInfo", GetTokenInfoDto{
		Token: token,
	})
}

func newAuthService() fx.Option {
	return fx.Module("AuthService",
		fx.Provide(func(rpc *app.RPC, e *app.Emitter) *AuthService {
			service := &AuthService{
				rpc:      rpc,
				emitter:  e,
				sessions: map[string]*types.TokenInfo{},
				tokens:   map[string]string{},
			}

			e.OnDisconnection(service.disconnectHandler)
			e.OnConnection(service.connectHandler)

			return service
		}),
	)
}
